/***************************************************************************
 *   Copyright (C) 2004 by cyril dupuit                                    *
 *   cyrildupuit@hotmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//*****************************************************************************
// Nom du module : stdlib.c
// Description : Definition de la librairie standard de c (ANSI ou preqsque)
//*****************************************************************************
 
// Historique :
// 28/10/04 : Creation du module V1.0

#include "stdlib.h"
#include "string.h"
#include "Lib/StdLib/math.h"

//*****************************************************************************

#define MODULUS		2147483647L
#define FACTOR          16807L
#define DIVISOR  	127773L
#define REMAINDER       2836L

//*****************************************************************************

static int last_val;

//*****************************************************************************

static void xtoa (unsigned long val, char *buf, unsigned radix, int is_neg);

//*****************************************************************************

int rand(void)
{
	int last_div = (int)last_val / DIVISOR;
	int last_rem = (int)last_val % DIVISOR;
	
	last_val = (FACTOR * last_rem) - (REMAINDER * last_div);

	if(last_val < 0) last_val += MODULUS;
	
	return (int)last_val;
}

//*****************************************************************************

void srand(unsigned int seed)
{
    last_val = seed;
}

//*****************************************************************************
// But de la fonction : Convertir une chaine de caractere en entier long non
// signe
// Entree : 
//	pDigit : Pointeur sur la chaine de caractere
// Parametre retourne : Chaine de caractere convertie
//*****************************************************************************
unsigned long atoul(char * pDigit)
{
    	unsigned long Result = 0;
    	unsigned int I = 0;
    	unsigned long Weight = 1;
    
    	while(pDigit[I] != '\0') I++;//Calculer la taille de la chaine
	if(I == 0) return 0;//La chaine est vide
    	I--;//Retirer les unites
	while(I > 0)
	{//Calculer la puissance de 10
		Weight *= 10;
		I--;
	}

	while(*pDigit != '\0')
	{
		if(Weight == 0) Weight = 1;
		
		if(((*pDigit - '0') >= 0)&&((*pDigit - '0') <= 9))
		{//Si digit compris entre 0 et 9, faire le calcul
			Result += Weight * (*pDigit - '0');	
		}
		pDigit++;
		Weight /= 10;
	}
    
	return Result;
}

//*****************************************************************************

char * itoa (int val, char *buf, int radix)
{
        if (radix == 10 && val < 0)
            xtoa((unsigned long)val, buf, radix, 1);
        else
            xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
        return buf;
}

char * ltoa (long val, char *buf, int radix)
{
        xtoa((unsigned long)val, buf, radix, (radix == 10 && val < 0));
        return buf;
}

char * ultoa (unsigned long val, char *buf, int radix)
{
        xtoa(val, buf, radix, 0);

        return buf;
}

static void xtoa (unsigned long val, char *buf, unsigned radix, int is_neg)
{
	char *p;                /* pointer to traverse string */
	char *firstdig;         /* pointer to first digit */
	char temp;              /* temp char */
	unsigned digval;        /* value of digit */

	p = buf;

	if(is_neg != 0)
	{/* negative, so output '-' and negate */
		*p++ = '-';
		val = (unsigned long)(-(long)val);
	}

	firstdig = p;           /* save pointer to first digit */

	do
	{
		digval = (unsigned) (val % radix);
		val /= radix;       /* get next digit */

		/* convert to ascii and store */
		if (digval > 9)
		{
			*p++ = (char) (digval - 10 + 'a');  /* a letter */
		}
		else
		{
			*p++ = (char) (digval + '0');       /* a digit */
		}
	}
	while (val > 0);

	/* We now have the digit of the number in the buffer, but in reverse
	order.  Thus we reverse them now. */

	*p-- = '\0';            /* terminate string; p points to last digit */

	do
	{
		temp = *p;
		*p = *firstdig;
		*firstdig = temp;   /* swap *p and *firstdig */
		--p;
		++firstdig;         /* advance to next two digits */
	}
	while (firstdig < p); /* repeat until halfway */
}

//*****************************************************************************
long unsigned strtou(const char *s, int base, char **scan_end)
{
	int value,overflow = 0;
	long unsigned result = 0,oldresult;
	/* Skip trailing zeros */
	while (*s == '0') s++;
	if (*s == 'x' && base == 16) 
	{
		s++;
		while (*s == '0') s++;
	}
	/* Convert number */
	while(isnumber(*s,base))
	{
		value = tonumber(*s++);
		if((value > base)||(value < 0)) return 0;
		oldresult = result;
		result *= base;
		result += value;
		/* Detect overflow */
		if (oldresult > result) overflow = 1;
	}
	if(scan_end != 0L) *scan_end = (char *)s;
	if(overflow) result = INT_MAX;
	
	return(result);
}

unsigned long strtoul(const char *nptr, char **endptr, int base)
{
	const char *s = nptr;
	unsigned long acc;
	unsigned char c;
	unsigned long cutoff;
	int neg = 0, any, cutlim;

	/*
	 * See strtol for comments as to the logic used.
	 */
	do {
		c = *s++;
	} while (isspace(c));
	if (c == '-') {
		neg = 1;
		c = *s++;
	} else if (c == '+')
		c = *s++;
	if ((base == 0 || base == 16) &&
	    c == '0' && (*s == 'x' || *s == 'X')) {
		c = s[1];
		s += 2;
		base = 16;
	}
	if (base == 0)
		base = c == '0' ? 8 : 10;
	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
	for (acc = 0, any = 0;; c = *s++) {
/*		if (!isascii(c))*/
		if (!isalnum(c))
			break;
		if (isdigit(c))
			c -= '0';
		else if (isalpha(c))
			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
		else
			break;
		if (c >= base)
			break;
		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
			any = -1;
		else {
			any = 1;
			acc *= base;
			acc += c;
		}
	}
	if (any < 0) {
		acc = ULONG_MAX;
//		errno = ERANGE;
	} else if (neg)
		acc = -acc;
	if (endptr != 0)
		*endptr = (char *)(any ? s - 1 : nptr);
	return (acc);
}

long int strtoi(char *s,int base,char **scan_end)
{
	int sign,value,overflow = 0;
	long int result = 0,oldresult;
	/* Evaluate sign */
	if (*s == '-')
	{
		sign = -1;
		s++;
	}
	else if(*s == '+')
	{
		sign = 1;
		s++;
	}
	else sign = 1;
	/* Skip trailing zeros */
	while(*s == '0') s++;
	/* Convert number */
	while(isnumber(*s,base))
	{
		value = tonumber(*s++);
		if (value > base || value < 0) return(0);
		oldresult = result;
		result *= base;
		result += value;
		/* Detect overflow */
		if (oldresult > result) overflow = 1;
	}
	if(scan_end != 0L) *scan_end = s;
	if(overflow) result = INT_MAX;
	result *= sign;
	
	return result;
}

double strtod(char *s,char **scan_end)
{
	int sign,i;
	double result = 0;
	double value;
	double mantissa = 0,divisor = 1;
	unsigned short power = 0;
	/* Evaluate sign */
	if (*s == '-')
	{
		sign = -1;
		s++;
	}
	else sign = 1;
	/* Skip trailing zeros */
	while (*s == '0') s++;
	/* Convert integer part */
	while (*s <= '9' && *s >= '0')
	{
		value = *s++ - '0';
		result *= 10.0;
		result += value;
	}
	/* Detect floating point & mantissa */
	if (*s == '.')
	{
		s++;
		while (*s <= '9' && *s >= '0')
		{
		value = *s++ - '0';
		mantissa *= 10.0;
		mantissa += value;
		divisor *= 10.0;
		}
	}
	mantissa /= divisor;
	/* Adjust result */
	result += mantissa;
	/* Adjust sign */
	result *= sign;
	/* Detect exponent */
	if (*s == 'e' || *s == 'E')
	{
		s++;
		if (*s == '-') 
		{
			sign = -1;
	    		s++;
		}
		else if(*s == '+')
		{
			sign = 1;
			s++;
		}
		else sign = 1;
		while (*s <= '9' && *s >= '0')
		{
			value = *s++ - '0';
			power *= 10.0;
			power += value;
		}
	}
	/* Adjust result on exponent sign */
	if (sign > 0)
	{
		for (i = 0; i < power; i++) result *= 10.0;
	}
	else
	{
		for (i = 0; i < power; i++) result /= 10.0;
	}
	if (scan_end != 0L) *scan_end = s;
	
	return(result);
}

//*****************************************************************************
